﻿using System;
using System.Net;
using System.Runtime.Serialization;

namespace Toybox.NicoSharp.Video.MyPage
{
	using Abstracts;

	public class Mylist : MyPagePrimitives.AbstractMyPageList
	{

		#region Constructor

		public Mylist(string group_id, CookieCollection cookies = null)
			: base(cookies)
		{
			this.Id = group_id;

			this.Token = new Token(NicoUrls.VideoTop + "my/mylist/#/" + this.Id);
			this.Token.Type = TokenType.NicoAPI;
		}

		#endregion Constructor


		#region Public Members

		public string Id
		{
			get;
			protected set;
		}

		#endregion Public Members


		#region Public Methods

		public ListResult List()
		{
			return this.MethodL<ListResult>("list");
		}

		public AddResult Add(Item item)
		{
			return this.MethodAU<AddResult>("add", item);
		}

		public UpdateResult Update(Item item)
		{
			return this.MethodAU<UpdateResult>("update", item);
		}

		public DelResult Delete(Item item)
		{
			return this.Delete(new Item[] { item });
		}

		public DelResult Delete(Item[] items)
		{
			return this.MethodD<DelResult>("delete", items);
		}

		public MoveResult Move(string target_group_id, Item item)
		{
			return this.Move(target_group_id, new Item[] { item });
		}

		public MoveResult Move(string target_group_id, Item[] items)
		{
			return MethodMC<MoveResult>("move", target_group_id, items);
		}

		public CopyResult Copy(string target_group_id, Item item)
		{
			return Copy(target_group_id, new Item[] { item });
		}

		public CopyResult Copy(string target_group_id, Item[] items)
		{
			return MethodMC<CopyResult>("copy", target_group_id, items);
		}

		#endregion Public Methods

		#region Protected Methods

		protected override string GetUrl(string method)
		{
			return NicoUrls.FlApi + "mylist/" + method;
		}

		/// <summary>
		/// Listで使用
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="method"></param>
		/// <param name="item"></param>
		/// <returns></returns>
		protected virtual T MethodL<T>(string method)
		{
			string url = GetUrl(method);
			string data = "group_id=" + this.Id;
			return this.Post<T>(url, data);
		}

		/// <summary>
		/// Add, Updateで使用
		/// </summary>
		/// <param name="group_id"></param>
		/// <param name="method"></param>
		/// <param name="item"></param>
		/// <returns></returns>
		protected virtual T MethodAU<T>(string method, Item item)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl(method);
			string data = "group_id=" + this.Id + "&" + item.ToString() + "&token=" + this.Token.Value;
			return this.Post<T>(url, data);
		}

		/// <summary>
		/// Deleteで使用
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="method"></param>
		/// <param name="items"></param>
		/// <returns></returns>
		protected virtual T MethodD<T>(string method, Item[] items)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = this.GetUrl(method);
			string data = "group_id=" + this.Id;
			foreach (Item item in items)
				data += "&" + item.ToStringForList();

			data += "&token=" + this.Token.Value;

			return this.Post<T>(url, data);
		}

		/// <summary>
		/// Move, Copyで使用
		/// </summary>
		/// <param name="group_id"></param>
		/// <param name="method"></param>
		/// <param name="target_group_id"></param>
		/// <param name="items"></param>
		/// <returns></returns>
		protected virtual T MethodMC<T>(string method, string target_group_id, Item[] items)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl(method);
			string data = "group_id=" + this.Id + "&target_group_id=" + target_group_id;
			foreach (Item item in items)
				data += "&" + item.ToStringForList();

			data += "&token=" + this.Token.Value;

			return this.Post<T>(url, data);
		}

		#endregion Protected Methods


		#region [SubClass]

		[DataContract]
		public class ListResult : AbstractStatus
		{
			[DataMember]
			public Item[] mylistitem;

			#region [SubClass]

			[DataContract]
			public class Item
			{
				[DataMember]
				public ItemType item_type;

				[DataMember]
				public string item_id;

				[DataMember]
				public string description;

				[DataMember]
				public Item_Data item_data;

				[DataMember]
				public string watch;

				[DataMember]
				public int create_time;

				[DataMember]
				public int update_time;
			}

			[DataContract]
			public class Item_Data
			{
				[DataMember]
				public string video_id;

				[DataMember]
				public string title;

				[DataMember]
				public Uri thumbnail_url;

				[DataMember]
				public int first_retrieve;

				[DataMember]
				public int update_time;

				[DataMember]
				public int view_counter;

				[DataMember]
				public int mylist_counter;

				[DataMember]
				public int num_res;

				[DataMember]
				public string group_type;

				[DataMember]
				public int length_seconds;

				[DataMember]
				public int deleted;

				[DataMember]
				public string last_res_body;

				[DataMember]
				public string watch_id;
			}

			#endregion [SubClass]
		}

		[DataContract]
		public class AddResult : AbstractStatus
		{
		}

		[DataContract]
		public class UpdateResult : AbstractStatus
		{
		}

		[DataContract]
		public class DelResult : AbstractStatus
		{
			[DataMember]
			public int delete_count;
		}

		[DataContract]
		public class MoveResult : AbstractStatus
		{
			[DataMember]
			public Items matches;

			[DataMember]
			public Items duplicates;

			[DataMember]
			public Items targets;

			#region [SubClass]

			[DataContract]
			public class Items
			{
				[DataMember]
				public Item[] item;
			}

			[DataContract]
			public class Item
			{
				[DataMember]
				public string type;

				[DataMember]
				public string id;
			}

			#endregion [SubClass]

		}

		[DataContract]
		public class CopyResult : MoveResult
		{
		}

		#endregion [SubClass]

	}
}
